package com.library.logging.aspect;

import com.alibaba.fastjson.JSON;
import com.library.logging.modules.operationlog.service.OperationLogService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import java.util.Objects;

/**
 * 操作日志切面
 *
 * @author: xyh
 * @create: 2023-05-20
 **/

@Slf4j(topic = "operaErr")
@Aspect
@Component
public class LogAspect {

    @Resource
    private OperationLogService operationLogService;

    /**
     * 配置切入点
     */
    @Pointcut("@annotation(com.library.logging.annotation.LogSys)")
    public void logPointcut() {
        // 该方法无方法体,主要为了让同类中其他方法使用此切入点
    }

    /**
     *  方法用途:在AnnotationDemo注解之前执行，标识一个前置增强方法，相当于BeforeAdvice的功能
     */
    @Before("logPointcut()")
    public void doBefore(JoinPoint joinPoint) {
        log.info("进入方法前执行...");
    }

    @AfterReturning(value = "logPointcut()", returning = "result")
    public void logAround(JoinPoint joinPoint, Object result) throws Throwable {
        // 获取RequestAttributes
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes != null) {
            // 从获取RequestAttributes中获取HttpServletRequest的信息
            HttpServletRequest request = (HttpServletRequest) Objects.requireNonNull(requestAttributes).resolveReference(RequestAttributes.REFERENCE_REQUEST);
            saveSysLogAsync(request, joinPoint, result);
        } else {
            //未登录请求，计入日志文件
            log.error("未登录请求，请求信息为：{}", joinPoint);
        }

    }

    /**
     * 异步保存系统日志
     */
    @Async(value = "taskExecutor")
    public void saveSysLogAsync(HttpServletRequest request, final JoinPoint joinPoint, Object ret) {
        log.info("异步保存日志 start ====> {}, 返回信息：{}", joinPoint, ret);
        operationLogService.insert(request, joinPoint, JSON.toJSONString(ret));
    }

}
